package edu.ccut.saturn.manager.bundles.core;

import java.util.List;
import java.util.Map;

import edu.ccut.saturn.component.DefaultComponent;
import edu.ccut.saturn.component.IParameterContext;

public class GetGraphicCode extends DefaultComponent{
	
	private static double POINT_L = 5;

	private static double POINT_LC = 8.6;

	private static double point_length;

	private String datasrc;
	
	private static final String PIC_PATH = "/edu.ccut.saturn.manager.bundles.impl/extComponentModule/page/images/";

	// 组件名称
	private static final String COMP_NAME = "name";

	// 组件fullKey
	private static final String COMP_FULLkEY = "fullKey";

	// 组件描述
	private static final String COMP_DESCRIPTION = "description";

	// 组件类型
	private static final String COMP_TYPE = "type";

	// 组件节点信息
	private static final String COMP_NODE_INFOS = "nodeInfos";

	// 节点id
	private static final String COMP_NODE_ID = "nodeId";

	// 节点名称
	private static final String COMP_NODE_NAME = "nodeName";

	// 下一节点id
	private static final String COMP_NODE_NEXT_ID = "nextNodeId";

	// 节点类型为Decision时的thenId
	private static final String COMP_NODE_THEN_ID = "nodeThenId";

	// 节点类型为Decision时的elseId
	private static final String COMP_NODE_ELSE_ID = "nodeElseId";

	// 节点类型为组件时的异常几点id
	private static final String COMP_NODE_EXCEPTION_ID = "exceptionId";

	// 节点描述
	private static final String COMP_NODE_DESCRIPTION = "nodeDescription";

	// 节点x坐标值
	private static final String COMP_NODE_X = "nodeX";

	// 节点y坐标值
	private static final String COMP_NODE_Y = "nodeY";

	// 节点类型
	private static final String COMP_NODE_TYPE = "nodeType";

	// 节点为组件节点时的fullKey
	private static final String COMP_NODE_KEY = "nodeKey";

	private static final String BlACK = "#000000";
	private static final String RED = "#ff0000";
	private static final String GREEN = "#00ff00";

	@Override
	public void execute(IParameterContext parameterContext) throws Exception {
		
		String result = getPrint(parameterContext).toString();
		
		parameterContext.setParameter(2, result);
	}
	
	//public void doTag() throws IOException {
	//	JspWriter jspWriter = getJspContext().getOut();
	//	jspWriter.print(getPrint());
	//}

	private StringBuffer getPrint(IParameterContext parameterContext) throws Exception {
		
		// TODO:从上下文中取得信息对象
		//HttpServletRequest httpServletRequest = (HttpServletRequest) ((PageContext) getJspContext())
		//		.getRequest();
		//Map<String, Object> infoMap = (Map<String, Object>) httpServletRequest
		//		.getAttribute(datasrc);
		
		Map<String, Object> infoMap = (Map<String, Object>)parameterContext.getParameterValue(0);
		
		String pathContext = (String)parameterContext.getParameterValue(1);

		List<Map<String, String>> nodeInfoList = (List<Map<String, String>>) infoMap
				.get(COMP_NODE_INFOS);

		StringBuffer stringBuffer = new StringBuffer();

		for (int i = 0; i < nodeInfoList.size(); i++) {

			stringBuffer.append("<script type='text/javascript'>");
			Map<String, String> nodeInfoMap = (Map<String, String>) nodeInfoList
					.get(i);
            nodeInfoMap.put(COMP_FULLkEY, (String)infoMap.get(COMP_FULLkEY));
			if (nodeInfoMap.get(COMP_NODE_TYPE).equals("decision")) {

				stringBuffer.append(getMethodHead(nodeInfoMap,
						getNodeInfoMapFromList(nodeInfoList, nodeInfoMap
								.get(COMP_NODE_THEN_ID)), BlACK));

				stringBuffer.append(getMethodHead(nodeInfoMap,
						getNodeInfoMapFromList(nodeInfoList, nodeInfoMap
								.get(COMP_NODE_ELSE_ID)), GREEN));
			} else {

				if (nodeInfoMap.get(COMP_NODE_NEXT_ID) != null
						&& !nodeInfoMap.get(COMP_NODE_NEXT_ID).equals("")) {

					stringBuffer.append(getMethodHead(nodeInfoMap,
							getNodeInfoMapFromList(nodeInfoList, nodeInfoMap
									.get(COMP_NODE_NEXT_ID)), BlACK));

					if (nodeInfoMap.get(COMP_NODE_TYPE).equals("component")
							|| nodeInfoMap.get(COMP_NODE_TYPE).equals("logic")) {

						if (nodeInfoMap.get(COMP_NODE_EXCEPTION_ID) != null
								&& !nodeInfoMap.get(COMP_NODE_EXCEPTION_ID)
										.equals("")) {
							stringBuffer
									.append(getMethodHead(
											nodeInfoMap,
											getNodeInfoMapFromList(
													nodeInfoList,
													nodeInfoMap
															.get(COMP_NODE_EXCEPTION_ID)),
											RED));
						}
					}
				}
			}

			stringBuffer.append("</script>");
			stringBuffer
					.append(getImageString(nodeInfoMap, pathContext
							//, httpServletRequest
							));
		}

		return stringBuffer;
	}

	/**
	 * 根据nodeId，从list中获取NodeInfoMap
	 * 
	 * @param nodeInfoList
	 * @param nodeId
	 * @return
	 */
	private Map<String, String> getNodeInfoMapFromList(
			List<Map<String, String>> nodeInfoList, String nodeId) {

		for (Map<String, String> nodeInfo : nodeInfoList) {
			if (nodeId.equals(nodeInfo.get(COMP_NODE_ID))) {
				return nodeInfo;
			}
		}
		return null;
	}

	private StringBuffer getMethodHead(Map<String, String> nodeInfoMap,
			Map<String, String> nodeInfoMap2, String color) {

		StringBuffer stringBuffer = new StringBuffer();

		stringBuffer.append(getMethodHeadOfLine(nodeInfoMap, nodeInfoMap2,
				color));

		stringBuffer.append(getMethodHeadOfTriangle(nodeInfoMap, nodeInfoMap2,
				"A", "B", color));
		stringBuffer.append(getMethodHeadOfTriangle(nodeInfoMap, nodeInfoMap2,
				"A", "C", color));
		stringBuffer.append(getMethodHeadOfTriangle(nodeInfoMap, nodeInfoMap2,
				"B", "C", color));
		return stringBuffer;
	}

	/**
	 * 取得输出图象的字符串
	 * 
	 * @param nodeInfoMap
	 * @return stringBuffer
	 */
	private StringBuffer getImageString(Map<String, String> nodeInfoMap
			,String pathContext
			//, HttpServletRequest request
			) {
		StringBuffer stringBuffer = new StringBuffer();
		String name = nodeInfoMap.get(COMP_NODE_NAME);
		stringBuffer
				.append("<div style=\"text-align:center;position:absolute;border:0;left:");
		stringBuffer.append(getX(nodeInfoMap));
		stringBuffer.append(";top:");
		stringBuffer.append(getY(nodeInfoMap));
		stringBuffer.append(";\">");
		stringBuffer.append("<IMG alt=\"");
		stringBuffer.append(nodeInfoMap.get(COMP_NODE_NAME));

		//stringBuffer.append("\" SRC=\"" + request.getContextPath());
		
		stringBuffer.append("\" SRC=\"" + pathContext);
		//TODO 平台管理引用路径
		stringBuffer.append(PIC_PATH
				+ nodeInfoMap.get("nodeType") + ".gif");
		stringBuffer.append("\"");

		if (nodeInfoMap.get("nodeType").equals("action")
				|| nodeInfoMap.get("nodeType").equals("logic")) {
			//add by yanshuang begin
			stringBuffer.append(" ondblclick=\"graphicByFullKey(" 
					+ "'" + nodeInfoMap.get(COMP_NODE_ID) + "'" 
					+ "," 
					+ "'" + nodeInfoMap.get(COMP_FULLkEY) + "'" 
			        + ")");
			//add by yanshuang end
		}

		stringBuffer.append("\"/><br>");

		String afterName = name;

		while (afterName.length() > 6) {
			String aaa = afterName.substring(0, 4);
			afterName = afterName.substring(4, afterName.length());
			stringBuffer.append(aaa + "<br>");
		}
		stringBuffer.append(afterName);
		stringBuffer.append("</div>");
		return stringBuffer;
	}

	/**
	 * 取得画线方法头
	 * 
	 * @param nodeInfoMap
	 * @param nodeInfoMap2
	 * @return stringBuffer
	 */
	private StringBuffer getMethodHeadOfLine(Map<String, String> nodeInfoMap,
			Map<String, String> nodeInfoMap2, String color) {

		StringBuffer stringBuffer = new StringBuffer();
		double x1 = getFirstPiontX(getX(nodeInfoMap) + 20,
				getY(nodeInfoMap) + 20, getX(nodeInfoMap2) + 20,
				getY(nodeInfoMap2) + 20);
		double y1 = getFirstPiontY(getX(nodeInfoMap) + 20,
				getY(nodeInfoMap) + 20, getX(nodeInfoMap2) + 20,
				getY(nodeInfoMap2) + 20);
		double x2 = getNextPiontX(getX(nodeInfoMap) + 20,
				getY(nodeInfoMap) + 20, getX(nodeInfoMap2) + 20,
				getY(nodeInfoMap2) + 20);
		double y2 = getNextPiontY(getX(nodeInfoMap) + 20,
				getY(nodeInfoMap) + 20, getX(nodeInfoMap2) + 20,
				getY(nodeInfoMap2) + 20);

		stringBuffer.append("color=\"" + color + "\";lineWidth=1;Line(" + x1
				+ getMock() + y1 + getMock() + x2 + getMock() + y2
				+ ");Ox = -1;Oy = -1; ");
		return stringBuffer;
	}

	/**
	 * 取得画三角箭头线的方法头
	 * 
	 * @param nodeInfoMap
	 * @param nodeInfoMap2
	 * @param one
	 * @param next
	 * @return stringBuffer
	 */
	private StringBuffer getMethodHeadOfTriangle(
			Map<String, String> nodeInfoMap, Map<String, String> nodeInfoMap2,
			String one, String next, String color) {

		StringBuffer stringBuffer = new StringBuffer();
		double x1 = getFirstPiontX(getX(nodeInfoMap) + 20,
				getY(nodeInfoMap) + 20, getX(nodeInfoMap2) + 20,
				getY(nodeInfoMap2) + 20);
		double y1 = getFirstPiontY(getX(nodeInfoMap) + 20,
				getY(nodeInfoMap) + 20, getX(nodeInfoMap2) + 20,
				getY(nodeInfoMap2) + 20);
		double x2 = getNextPiontX(getX(nodeInfoMap) + 20,
				getY(nodeInfoMap) + 20, getX(nodeInfoMap2) + 20,
				getY(nodeInfoMap2) + 20);
		double y2 = getNextPiontY(getX(nodeInfoMap) + 20,
				getY(nodeInfoMap) + 20, getX(nodeInfoMap2) + 20,
				getY(nodeInfoMap2) + 20);

		stringBuffer.append("color=\"" + color + "\";lineWidth=1;Line("
				+ getPointX(x1, y1, x2, y2, one) + getMock()
				+ getPointY(x1, y1, x2, y2, one) + getMock()
				+ getPointX(x1, y1, x2, y2, next) + getMock()
				+ getPointY(x1, y1, x2, y2, next) + ");Ox = -1;Oy = -1; ");

		return stringBuffer;
	}

	/**
	 * 得到x坐标
	 * @param nodeInfoMap
	 * @return
	 */
	private int getX(Map<String, String> nodeInfoMap) {
		return Integer.parseInt(nodeInfoMap.get(COMP_NODE_X));
	}

	/**
	 * 得到y坐标
	 * @param nodeInfoMap
	 * @return
	 */
	private int getY(Map<String, String> nodeInfoMap) {
		return Integer.parseInt(nodeInfoMap.get(COMP_NODE_Y));
	}

	public static String getMock() {
		return ",";
	}

	public String getDatasrc() {
		return datasrc;
	}

	public void setDatasrc(String datasrc) {
		this.datasrc = datasrc;
	}

	/**
	 * 计算三角线端点x坐标
	 * 
	 * @param x1
	 * @param y1
	 * @param x2
	 * @param y2
	 * @param point
	 * @return value
	 */
	public static double getPointX(double x1, double y1, double x2, double y2,
			String point) {
		double AB_x;
		double C_x;
		double value = 0;

		point_length = Math
				.sqrt(((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)));
		AB_x = POINT_L * (y2 - y1) / point_length;
		C_x = POINT_LC * (x2 - x1) / point_length;
		if (point.equals("A")) {
			value = AB_x + x2;
		}
		if (point.equals("B")) {
			value = x2 - AB_x;
		}
		if (point.equals("C")) {
			value = x2 + C_x;
		}
		return value;

	}

	/**
	 * 取得三角端点y坐标
	 * 
	 * @param x1
	 * @param y1
	 * @param x2
	 * @param y2
	 * @param point
	 * @return
	 */
	public static double getPointY(double x1, double y1, double x2, double y2,
			String point) {
		double AB_y;
		double C_y;
		double value = 0;

		point_length = Math
				.sqrt(((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)));
		AB_y = POINT_L * (x2 - x1) / point_length;
		C_y = POINT_LC * (y2 - y1) / point_length;

		if (point.equals("A")) {
			value = y2 - AB_y;
		}
		if (point.equals("B")) {
			value = y2 + AB_y;
		}
		if (point.equals("C")) {
			value = y2 + C_y;
		}
		return value;
	}

	private double getFirstPiontY(double x1, double y1, double x2, double y2) {
		if (x2 >= x1 && y2 >= y1) {
			return y1
					+ Math.sqrt(800 * (y2 - y1) * (y2 - y1)
							/ ((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1)));
		} else if (x2 >= x1 && y2 <= y1) {
			return y1
					- Math.sqrt(800 * (y1 - y2) * (y1 - y2)
							/ ((x2 - x1) * (x2 - x1) + (y1 - y2) * (y1 - y2)));
		} else if (x2 <= x1 && y2 >= y1) {
			return y1
					+ Math.sqrt(800 * (y2 - y1) * (y2 - y1)
							/ ((x1 - x2) * (x1 - x2) + (y2 - y1) * (y2 - y1)));
		} else {
			return y1
					- Math.sqrt(800 * (y1 - y2) * (y1 - y2)
							/ ((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));
		}

	}

	private double getFirstPiontX(double x1, double y1, double x2, double y2) {
		if (x2 >= x1 && y2 >= y1) {
			return x1
					+ Math.sqrt(800 * (x2 - x1) * (x2 - x1)
							/ ((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1)));
		} else if (x2 >= x1 && y2 <= y1) {
			return x1
					+ Math.sqrt(800 * (x2 - x1) * (x2 - x1)
							/ ((x2 - x1) * (x2 - x1) + (y1 - y2) * (y1 - y2)));
		} else if (x2 <= x1 && y2 >= y1) {
			return x1
					- Math.sqrt(800 * (x1 - x2) * (x1 - x2)
							/ ((y2 - y1) * (y2 - y1) + (x1 - x2) * (x1 - x2)));
		} else {
			return x1
					- Math.sqrt(800 * (x1 - x2) * (x1 - x2)
							/ ((y1 - y2) * (y1 - y2) + (x1 - x2) * (x1 - x2)));
		}
	}

	private double getNextPiontY(double x1, double y1, double x2, double y2) {
		if (x2 >= x1 && y2 >= y1) {
			return y2
					- Math.sqrt(800 * (y2 - y1) * (y2 - y1)
							/ ((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1)));
		} else if (x2 >= x1 && y2 <= y1) {
			return y2
					+ Math.sqrt(800 * (y1 - y2) * (y1 - y2)
							/ ((x2 - x1) * (x2 - x1) + (y1 - y2) * (y1 - y2)));
		} else if (x2 <= x1 && y2 >= y1) {
			return y2
					- Math.sqrt(800 * (y2 - y1) * (y2 - y1)
							/ ((y2 - y1) * (y2 - y1) + (x1 - x2) * (x1 - x2)));
		} else {
			return y2
					+ Math.sqrt(800 * (y1 - y2) * (y1 - y2)
							/ ((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));
		}
	}

	private double getNextPiontX(double x1, double y1, double x2, double y2) {
		if (x2 >= x1 && y2 >= y1) {
			return x2
					- Math.sqrt(800 * (x2 - x1) * (x2 - x1)
							/ ((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1)));
		} else if (x2 >= x1 && y2 <= y1) {
			return x2
					- Math.sqrt(800 * (x2 - x1) * (x2 - x1)
							/ ((x2 - x1) * (x2 - x1) + (y1 - y2) * (y1 - y2)));
		} else if (x2 <= x1 && y2 >= y1) {
			return x2
					+ Math.sqrt(800 * (x1 - x2) * (x1 - x2)
							/ ((x1 - x2) * (x1 - x2) + (y2 - y1) * (y2 - y1)));
		} else {
			return x2
					+ Math.sqrt(800 * (x1 - x2) * (x1 - x2)
							/ ((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));
		}
	}
}
